<?php defined('SYSPATH') or die('No direct script access.');

class Model_ProductParser_YML extends Model_ProductParser_Abstract
{ 
    protected $filename = null;         // Название файла
    protected $handler = null;          // Дескриптор файла
    protected $charset = null;          // Кодировка входного файла
    protected $shop = null;             // Магазин   
    
    /**
    * Парсим товары магазина
    * 
    * @param Model_Shop $shop
    */
    public function parse(Model_Shop $shop)
    {
        // Проверяем, используется урл или локальный файл
        // Если урл, то скачаваем его на локал
        $this->shop = $shop;
        if ($shop->is_parse_local()) {
            $this->filename = $shop->get_parse_local_path();   
        } else {
            //$this->filename = Model_Upload::upload($this->parse_url);   
        }
        
        $this->_open_file();   
        $this->_detect_charset();
        //$this->_seek_to_products_section();
        
        // Добавлям категории
        while ($category_data = $this->_get_category()) {
            $category_id = $this->_get_category_id($category_data);
            $name        = $this->_get_category_name($category_data);
            $parent_id   = $this->_get_category_parent_id($category_data);
            
            // TODO проверка, существует ли категория
            try { 
                ORM::factory('shop_category')->add_category($category_id, $name, $parent_id);
            } catch (Database_Exception $e) {
                if (strstr($e->getMessage(), 'Duplicate entry') !== false) {
                    continue;
                }
                die($e->getMessage());
            }
        }
        
        // Добавляем товары
        while ($product_data = $this->_get_product()) {
            $product_id = $this->_get_product_id($product_data);
            $category_id = $this->_get_product_category_id($product_data);
            $url        = $this->_get_product_url($product_data);
            $name       = $this->_get_product_name($product_data);
            $picture    = $this->_get_product_picture($product_data);
            
            // TODO проверка, существует ли данный товар и его обновление, засунуть в модель товара (process_product)
            // TODO in product model
            try {
                ORM::factory('product')->add_product($shop, $product_id, $category_id, $url, $name, $picture);
            } catch (Database_Exception $e) {
                if (strstr($e->getMessage(), 'Duplicate entry') !== false) {
                    continue;
                }
                die($e->getMessage());
            }
        }
        
        $this->_close_file();      
    }                
    
    protected function _get_product_id(&$product_data)
    {
        $product_id = $this->_cut_str(' id="', '"', $product_data); 
        return $product_id; 
    }
    
    protected function _get_product_category_id(&$product_data)
    {
        $category_id = $this->_cut_str('<categoryId>', '</categoryId>', $product_data); 
        return $category_id;  
    }
    
    protected function _get_product_url(&$product_data)
    {
        $url = $this->_cut_str('<url>', '</url>', $product_data);
        return $url;
    }
    
    protected function _get_product_name(&$product_data)
    {
        $name = $this->_cut_str('<name>', '</name>', $product_data);
        if (!trim($name)) {
            $vendor = $this->_cut_str('<vendor>', '</vendor>', $product_data);
            $model  = $this->_cut_str('<model>', '</model>', $product_data);
            $name   = $vendor.' '.$model;
            if (!trim($name)) {
                throw new Model_Exception('Имя товара не может быть пустым');
            }
        }
        return $this->_cut_quotes($name);  
    }
    
    protected function _get_product_picture(&$product_data)
    {
        $name = $this->_cut_str('<picture>', '</picture>', $product_data);
        return $this->_cut_quotes($name);  
    }
    
    protected function _get_category_id(&$category_data)
    {
        $category_id = $this->_cut_str(' id="', '"', $category_data);
        return $category_id;  
    }
    
    protected function _get_category_name(&$category_data)
    {
        $name = $this->_cut_str('>', '</', $category_data);
        return $this->_cut_quotes($name);  
    }
    
    protected function _get_category_parent_id(&$category_data)
    {
        $parent_id = $this->_cut_str('parentId="', '"', $category_data);
        return $parent_id;  
    }
    
    protected function _open_file()
    {
        $result = $this->handler = fopen($this->filename, 'r+'); 
        if (!$result) {
            throw new Model_Exception('Не удалось открыть файл');
        }
        return $result; 
    }
    
    protected function _detect_charset()
    {
        $str = fgets($this->handler);
        $charset = $this->_cut_str(' encoding="', '"', $str);
        
        if ($charset) {
            $this->charset = mb_strtolower($charset);
        } else {
            $this->charset = 'utf-8';
        }
    }
    
    protected function _encode($str)
    {
        if ($this->charset == 'utf-8') {
            return $str;
        }
        
        return iconv($this->charset, 'utf-8', $str);
    }
    
    protected function _get_product()
    {
        $data = null;
        while($str = fgets($this->handler)) {              
            if (strstr($str, '<offer') !== false) {
                $data = $str;
                
                while (strstr($str, '</offer>') === false) {
                    $data .= $str;
                    $str   = fgets($this->handler);
                }
                
                break;
            }
        }     
        return $this->_encode($data);
    }
    
    protected function _get_category()
    {
        $data = null;
        while($str = fgets($this->handler)) {
            if (strstr($str, '</categories>') !== false) {
                return false;
            }
                 
            if (strstr($str, '<category ') !== false) {
                $data = $str;
                
                while (strstr($str, '/category>') === false) {
                    $data .= $str;
                    $str   = fgets($this->handler);
                }
                
                break;
            }
        }  
        return $this->_encode($data);
    }
    
    protected function _close_file()
    {
        if (!fclose($this->handler)) {
            throw new Model_Exception('Не удалось закрыть файл');   
        }  
        return true; 
    }
    
    protected function _cut_quotes($str)
    {
        return trim(str_replace(array('<![CDATA[', ']]>'), '', $str));    
    }
}